/*
 * TouchLib.h
 *
 * @date 01.09.2014
 * @author Armin Joachimsmeyer
 *      Email:   armin.joachimsmeyer@gmail.com
 *      License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
 * @version 1.0.0
 */

#ifndef TOUCHLIB_H_
#define TOUCHLIB_H_

#include "BlueDisplay.h"

#ifdef LOCAL_DISPLAY_EXISTS
#include "ADS7846.h"
extern ADS7846 TouchPanel;
#endif

#define TOUCH_SWIPE_THRESHOLD 10  // threshold for swipe detection to suppress long touch handler calling
#define TOUCH_SWIPE_RESOLUTION_MILLIS 20

struct XYPosition {
    uint16_t PosX;
    uint16_t PosY;
};

struct TouchCallback {
    void (*OnTouchHandler)(uint16_t, int16_t);
    uint16_t ButtonIndex;
    uint16_t ButtonValue;
};

struct BluetoothEvent {
    uint8_t EventType;
    union EventData {
        struct XYPosition TouchPosition;
        struct XYSize DisplaySize;
        struct TouchCallback CallbackInfo;
    } EventData;
};

#ifdef LOCAL_DISPLAY_EXISTS
extern struct BluetoothEvent localTouchDownEvent;
extern struct BluetoothEvent localTouchEvent;
#endif
extern struct BluetoothEvent remoteTouchDownEvent;
extern struct BluetoothEvent remoteTouchEvent;

typedef struct {
    uint16_t TouchStartX;
    uint16_t TouchStartY;
    int16_t TouchDeltaX;
    int16_t TouchDeltaY;
    uint16_t TouchDeltaXAbs;  // = abs(TouchDeltaX)
    uint16_t TouchDeltaYAbs;
    int16_t TouchDeltaMax; // max of TouchDeltaX and Y
    uint16_t TouchDeltaAbsMax; // max of TouchDeltaXAbs and TouchDeltaYAbs to easily decide if swipe is large enough to be accepted
//    int SwipeAmount;
    bool SwipeMainDirectionIsX; // true if TouchDeltaXAbs >= TouchDeltaYAbs
} SWIPE_INFO;

extern struct XYPosition sDownPosition;
extern struct XYPosition sActualPosition;
extern struct XYPosition sUpPosition;

/*
 * helper variables
 */
extern bool sButtonTouched;
extern bool sAutorepeatButtonTouched;
extern bool sSliderTouched;
extern bool sNothingTouched;
extern bool sSliderIsMoveTarget;
void resetTouchFlags(void);

// can be one of the following:
//see also android.view.MotionEvent
#define EVENT_TAG_TOUCH_ACTION_DOWN 0x00
#define EVENT_TAG_TOUCH_ACTION_UP   0x01
#define EVENT_TAG_TOUCH_ACTION_MOVE 0x02
#define EVENT_TAG_TOUCH_ACTION_ERROR 0xFF
#define EVENT_TAG_CONNECTION_BUILD_UP 0x10
#define EVENT_TAG_RESIZE_ACTION 0x11

#define EVENT_TAG_FIRST_CALLBACK_ACTION 0x20
#define EVENT_TAG_BUTTON_CALLBACK_ACTION  0x20

#define EVENT_TAG_NO_EVENT 0xFF

extern volatile bool sDisableTouchUpOnce; // set normally by application if long touch action was made

void handleTouchUp(void);
bool checkAndHandleTouchEvents(void);

void registerPeriodicTouchCallback(bool (*aPeriodicTouchCallback)(int const, int const), const uint32_t aCallbackPeriodMillis);
void setPeriodicTouchCallbackPeriod(const uint32_t aCallbackPeriod);

void registerLongTouchCallback(bool (*aLongTouchCallback)(int const, int const), const uint32_t aLongTouchTimeoutMillis);

void registerEndTouchCallback(bool (*aEndTouchCallback)(SWIPE_INFO const));
void setEndTouchCallbackEnabled(bool aEndTouchCallbackEnabled);
bool (* getEndTouchCallback(void))(SWIPE_INFO const);

void registerSwipeEndCallback(void (*aSwipeEndCallback)(SWIPE_INFO const));
void setSwipeEndCallbackEnabled(bool aSwipeEndCallbackEnabled);

void registerConnectCallback(void (*aConnectCallback)(struct XYSize * const aMaxSize));
void registerSimpleConnectCallback(void (*aConnectCallback)(void));

void registerResizeCallback(void (*aResizeCallback)(struct XYSize * const aActualSize));
void registerSimpleResizeCallback(void (*aSimpleResizeCallback)(void));

void registerTouchDownCallback(void (*aTouchDownCallback)(struct XYPosition * const aActualPositionPtr));
void simpleTouchDownHandler(struct XYPosition * const aActualPositionPtr);
void simpleTouchDownHandlerForSlider(struct XYPosition * const aActualPositionPtr);

void registerTouchMoveCallback(void (*aTouchMoveCallback)(struct XYPosition * const aActualPositionPtr));
void simpleTouchMoveHandlerForSlider(struct XYPosition * const aActualPositionPtr);

void handleEvent(struct BluetoothEvent * aEvent);

#endif /* TOUCHLIB_H_ */
